package com.kjlink.widget.monitoring.xml;

import lombok.Getter;
import lombok.Setter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 描述:
 * 终上报的xml
 *
 * @author Vic.xu
 * @since 2025-08-04 10:13
 */
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "APPROOT")
public class AppRootXml implements Serializable {
    private static final long serialVersionUID = 1L;

    @XmlAttribute
    private String type = "BAMC_EVENT_REPORT";

    @XmlAttribute
    private String ver = "2,2";

    @XmlAttribute
    private String from = "F-AGCF";

    @XmlAttribute
    private String to = "F-AMC";

    @XmlAttribute
    private String mode = "asy";

    @XmlElement
    private ReportContentXml PUBLIC;

    // 提供构造函数方便使用
    public AppRootXml() {
    }

    public AppRootXml(ReportContentXml PUBLIC) {
        this.PUBLIC = PUBLIC;
    }

    public AppRootXml(String type, String ver, String from, String to, String mode, ReportContentXml publicData) {
        this.type = type;
        this.ver = ver;
        this.from = from;
        this.to = to;
        this.mode = mode;
        this.PUBLIC = publicData;
    }


    public static void main(String[] args) throws Exception {
        AppRootXml appRoot = AppRootXml.buildTestData();
        System.out.println(appRoot.toXml());
    }


    public String toXml() throws Exception {
        // 在序列化前填充空字段（只针对本类，不递归）
        fillNullFields(this.getPUBLIC());
        // 3. 使用 JAXB 序列化为 XML
        JAXBContext context = JAXBContext.newInstance(AppRootXml.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        // 设置编码为 GBK
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
        // 包含 XML 声明
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
        StringWriter writer = new StringWriter();
        marshaller.marshal(this, writer);
        String xml = writer.toString();

        //去除 standalone="yes"
        xml = xml.replace("standalone=\"yes\"", "");
        return xml;
    }

    public static AppRootXml buildTestData() {
        // 1. 构建 PUBLIC 数据
        ReportContentXml publicData = new ReportContentXml();
        publicData.setDATE("20091012093836");
        publicData.setAPPSNAME("F-AGCF");
        publicData.setTYPE("02");
        publicData.setTRANCODE("TRAN0001");
        publicData.setRESOURCECODE("");
        publicData.setEVENTCODE("COMMUNICATION");
        publicData.setRESOURCERATE("");
        publicData.setEVENTSCOUNT(1);
        publicData.setOCCURPLACE("82.209.15.61");
        publicData.setOCCURINSTANCE("abd9384ef9c9e12344ed90a9cb8276c5");
        publicData.setSOUCEAPPCODE("F-EBANKC");
        publicData.setTARGETAPPCODE("F-CGSE");
        publicData.setBUSINESSTYPE("业务种类一");
        publicData.setEXCEPTION("Error001");
        publicData.setSUBAPPID("上送应用服务群组ID");
        publicData.setSOURCESUBAPPID("业务源应用服务群组ID");
        publicData.setTARGETSUBAPPID("业务目标应用服务群组ID");
//        publicData.setBAKUP("备用字段1");
//        publicData.setOBJECT("监控对象");
        // 2. 构建根对象
        return new AppRootXml(publicData);
    }

    // 缓存ReportContentXml类的字段数组（只读缓存）
    private static final Map<Class<?>, Field[]> FIELD_CACHE = new ConcurrentHashMap<>();

    /**
     * 填充 ReportContentXml 对象中的空字段
     */
    public static void fillNullFields(ReportContentXml obj) throws IllegalAccessException {
        if (obj == null) {
            return;
        }
        Class<?> clazz = obj.getClass();
        Field[] fields = FIELD_CACHE.computeIfAbsent(clazz, c -> {
            Field[] fs = c.getDeclaredFields();
            for (Field f : fs) {
                f.setAccessible(true);
            }
            return fs;
        });

        for (Field field : fields) {
            Object value = field.get(obj);
            if (value == null) {
                Class<?> type = field.getType();
                if (type.equals(String.class)) {
                    field.set(obj, "");
                } else if (Number.class.isAssignableFrom(type)) {
                    // 可按需填默认值，比如 0
                    // field.set(obj, 0);
                } else if (!type.isPrimitive()) {
                    // 可扩展：对子对象递归处理
                    // fillNullFields(value);
                }
            }
        }
    }


}
